/*
    IceCode toolkit - Test Framework.
    Copyright (C) 2011 Alfredo 'IceCoder' Mungo

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _ICECODE_GALILEI_TEST
#define _ICECODE_GALILEI_TEST

#include <iostream>
#include <vector>
#include "assert.hpp"
#include "exception.hpp"
#include "print_macros.hpp"

#define ICECODE_TEST_RUN(t) int main() { t myTest; myTest.start(); return 0; }

//Run test (initialize the test class with arguments)
#define ICECODE_TEST_RUN_WARGS(t, desc) int main() { t myTest(desc); myTest.start(); return 0; }

namespace xmlpp {
  class Element;
}

namespace icecode {
  namespace test {

    class Test
    {
    public:
      Test() {}
      /*@! Initialize an instance of the Test class providing a description of the test. */
      Test(std::string desc) { this->desc = desc; }

      virtual void run() = 0;

      virtual int start()
      {
	init();

	try { run(); } catch (...) { test_fatal("Unexpected exception thrown. Please check your code."); ::exit(-1); }

	printResult();

	return errors;
      }

      void printResult()
      {
	float success = (tests - errors) * 100 / (tests > 0? tests: 1);

	std::cout << "\nPerformed tests:\t" << tests << std::endl;
	std::cout << "Failed tests:\t\t" << errors << std::endl;
	std::cout << "Success percentage:\t" << static_cast<unsigned short>(success) << "%\n";
      }

      unsigned int getTests() { return tests; }

    protected:
      unsigned int errors; //Number of failed tests
      unsigned int tests; //Number of performed tests
      std::string desc; //Test description
      std::vector<std::string> v_passed; //Passed test vector
      std::vector<std::string> v_failed; //Failed test vector

      void init()
      {
	errors = 0;
	tests = 0;

	v_passed.clear();
	v_passed.reserve(20);
	v_failed.clear();
	v_failed.reserve(20);

	if(!desc.empty())
	  std::cout << desc << std::endl << std::endl;
      }

      friend void icecode::test::internal_XMLOutput_Test(icecode::test::Test& t, xmlpp::Element* tst);
    };

  }
}

#endif //_ICECODE_GALILEI_TEST
